package servlet;

import bean.DealRecord;
import bean.User;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import dao.DealRecordDao;
import dao.UserDao;
import util.AlipayConfig;
import util.DealRecordUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用于接收支付宝异步通知并验签，交易记录数据入库（update（更改alipayStatus值）），单边账的删除
 * 特别的，由于支付宝官方对异步通知准确率的估计为99.9999%，所以有极小的概率产生单边账（即alipayStatus=1，非法订单）。
 *
 * @author dsf
 */
@WebServlet(name = "AlipayNotifyServlet", urlPatterns = "/notify")
public class AlipayNotifyServlet extends HttpServlet {

    /**
     * 接受支付宝异步通知验签，交易记录数据入库，单边账的删除
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = req.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        try {
            // 调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key,
                AlipayConfig.charset, AlipayConfig.sign_type);
            // 签名验证成功（需要返回success后支付宝才不在发出异步通知）
            if (signVerified) {
                // 交易记录id号
                String out_trade_no = new String(req.getParameter("out_trade_no").getBytes("ISO-8859-1"), "utf-8");
                // 支付宝交易号
                String trade_no = new String(req.getParameter("trade_no").getBytes("ISO-8859-1"), "utf-8");
                // 交易状态
                String trade_status = new String(req.getParameter("trade_status").getBytes("ISO-8859-1"), "utf-8");
                DealRecordDao drDao = new DealRecordDao();
                // 付款成功
                if (trade_status.equals("TRADE_SUCCESS")) {
                    // 付款成功后执行以下业务
                    DealRecord drSearchPara = new DealRecord();
                    drSearchPara.setDealRecordId(out_trade_no);
                    List<Object> drSearchRes;
                    try {
                        // 从数据库查找id对应的交易记录
                        drSearchRes = drDao.dealrecordSearch(null, drSearchPara, null);
                        // 可以匹配到交易记录
                        if (drSearchRes.size() != 0) {
                            DealRecord drSearchObject = (DealRecord) drSearchRes.get(0);
                            //存在的订单的确处于支付确认状态
                            if (drSearchObject.getAlipayStatus().equals("1")) {
                                //设置修改user表信息的参数
                                UserDao userDao = new UserDao();
                                User userModifyPara = new User();
                                userModifyPara.setUserId(drSearchObject.getUserId());
                                userModifyPara.setBalance(drSearchObject.getCurBalance());
                                //设置修改dealrecord表信息的参数
                                DealRecord drModifyPara = new DealRecord();
                                drModifyPara.setDealRecordId(out_trade_no);
                                // 修改alipayStatus值为2
                                drModifyPara.setAlipayStatus("2");
                                //执行修改dealrecord表操作
                                int drModifyRes = drDao.dealrecordModify(drModifyPara);
                                if (drModifyRes != 0) {
                                    //dealrecord表修改成功，证明充值成功完成且入库成功，修改user表的用户余额
                                    int userModifyRes = userDao.userModify(userModifyPara);
                                    if (userModifyRes != 0) {
                                        // 所有业务执行完毕，告知支付宝服务器交易成功，不必再发送异步通知
                                        resp.getWriter().println("success");
                                        resp.getWriter().close();
                                    } else {
                                        System.out.println("modify user table failed!");
                                    }
                                    //支付状态已完成，无需执行改表操作
                                } else {
                                    // 告知支付宝服务器交易成功，不必再发送异步通知
                                    resp.getWriter().println("success");
                                    resp.getWriter().close();
                                }
                                // 属于删除时间
                                if (DealRecordUtil.isDeleteTime()) {
                                    DealRecord drDelSearchPara = new DealRecord();
                                    //设置删除前进行非法订单查找的参数
                                    drDelSearchPara.setAlipayStatus("1");
                                    List<Object> drDelSearchRes = new ArrayList<Object>();
                                    // 查找数据库中的非法订单
                                    drDelSearchRes = drDao.dealrecordSearch(null, drSearchPara, null);
                                    // 的确存在非法订单
                                    if (drDelSearchRes.size() != 0) {
                                        for (int i = 0; i < drDelSearchRes.size(); i++) {
                                            DealRecord dr = (DealRecord) drDelSearchRes.get(i);
                                            String delActionTime = dr.getActionTime();
                                            // 而且此非法订单属于单边账
                                            if (DealRecordUtil.isIllegal(delActionTime)) {
                                                // 删除订单
                                                int delRes = drDao.dealrecordDelete(dr.getDealRecordId());
                                                if (delRes != 0) {
                                                    System.out.println("delete success!");
                                                } else {
                                                    System.out.println("delete failed!");
                                                }
                                            }
                                        }
                                    }
                                }
                            } else {
                                System.out.println("modify dealrecord failed!");
                            }
                            // 该id号不存在交易记录
                        } else {
                            System.out.println("No drId is same to what from alipay!");
                            return;
                        }
                    } catch (Exception e) {
                        System.out.println("get dr by id failed!");
                        e.printStackTrace();
                    }
                }
            } else {
                // 签名验证失败
                System.out.println("sign vertify failed!");

                // 调试用，写文本函数记录程序运行情况是否正常
                // String sWord = AlipaySignature.getSignCheckContentV1(params);
                // AlipayConfig.logResult(sWord);
            }
        } catch (AlipayApiException e) {
            // 抛出异常
            resp.getWriter().println("fail");
            resp.getWriter().close();
            e.printStackTrace();
        }
    }
}